import type { LearningDishwasherController } from './definition'
import type { Worker } from '@/controller/base/types/worker'
import type { Remote } from '@/controller/base/types/remote'
import {
  LearningPhaseKey,
  FeedbackRequested,
  FeedbackRequestedStillSatisfied,
  PresettingCleaning,
  PresettingDrying,
  PresettingDuration,
  LearningProgramKey,
  PresettingKeys,
} from './constants'
import { PRESENT, SELECTED_PROGRAM } from '@/constants/Command'
import type { DishwasherController } from '@/controller/Dishwasher/definition'
import { getLearningUsedCache, setLearningUsedCache } from './cache'

export const createLearningState: () => LearningDishwasherController.PureState = () => ({
  /**
   * 是否已使用过AI智洗
   */
  learningUsed: false,
  learningPhase: null,
  feedbackNoticeReceived: false,
  /**
   * 预设置
   */
  presetting: {
    [PresettingCleaning]: false,
    [PresettingDrying]: false,
    [PresettingDuration]: false,
  },
  presettingDisabled: false,
})

export const LearningGetters: LearningDishwasherController.Getters = {
  // 是否包含AI智洗程序
  learningSupported() {
    return this.allPrograms?.some((program) => program.key === LearningProgramKey) || false
  },
  // 当前是否为AI智洗程序
  learningProgramSelected() {
    // 当前程序为AI智洗 或 当前自定义程序为AI智洗
    return (
      this.currentProgramKey === LearningProgramKey ||
      (this.customProgramSelected && this.customProgramOption?.value === LearningProgramKey)
    )
  },
}

export const LearningActions: LearningDishwasherController.Actions = {
  /**
   * 设置是否已使用过AI智洗
   */
  setLearningUsed(used: boolean) {
    this.learningUsed = used
    const { haId } = this._datasource
    setLearningUsedCache(haId, used)
  },
  /**
   * 设置预设置值
   */
  setPresettingValue(key: string, value: boolean) {
    this.presetting[key] = value
  },
  /**
   * 评价反馈
   */
  // 重置评价反馈通知
  resetFeedbackNoticeReceived() {
    this.feedbackNoticeReceived = false
  },
}

type BatchObserve = Remote.BatchObserve<DishwasherController.Store>
/**
 * 详情页全局监听
 */
export const LearningGlobalObserves: BatchObserve[] = [
  /**
   * 设置预设置
   */
  {
    matcher: (msg) => PresettingKeys.includes(msg.key),
    handler(msg) {
      this.store.setPresettingValue(msg.key, msg.value as boolean)
    },
  },
  /**
   * 设置评价反馈通知
   */
  {
    matcher: (msg) => [FeedbackRequested, FeedbackRequestedStillSatisfied].includes(msg.key) && msg.value === PRESENT,
    handler() {
      this.store.feedbackNoticeReceived = true
    },
  },
]

/**
 * 弹框内监听
 */
export function getLearningModalObserves(payload: { onSwitchToOtherProgram: () => any }): BatchObserve[] {
  return [
    // 切换其他程序，自动关闭弹框
    {
      matcher: (msg) => msg.key === SELECTED_PROGRAM && msg.value !== LearningProgramKey,
      handler: payload.onSwitchToOtherProgram,
    },
  ]
}

export function useLearningEffects(control: DishwasherController.Control) {
  const { store, worker, remote } = control

  worker.onLoad(() => {
    // 回填缓存数据
    store.learningUsed = getLearningUsedCache(store._datasource.haId)

    return remote.loadAllEvents()
  })
  remote.addBatchObserves(LearningGlobalObserves as Remote.BatchObserve<DishwasherController.Store>[])

  useLearningBinding(control)

  /**
   * 回填预设置
   */
  watch(
    () => store._datasource.settings,
    (settings) => {
      settings.forEach((setting) => {
        if (PresettingKeys.includes(setting.key)) {
          store.setPresettingValue(setting.key, setting.value as boolean)
        }
      })
    }
  )
}

function useLearningBinding(control: DishwasherController.Control) {
  const { worker } = control

  worker.useGetValueBinding('learningPhase', {
    key: LearningPhaseKey,
    from: 'status',
  })
  worker.useHasKeysBinding('presettingDisabled', {
    keys: [PresettingCleaning, PresettingDrying, PresettingDuration],
    from: 'setting',
    patcher: (patchState, references) => {
      patchState.presettingDisabled = references.some((ref) => ref === null)
    },
  })
}
